package xgd

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"strconv"
	"strings"
	"time"
	"xlib/log"

	"github.com/gin-gonic/gin"

	D "TCP/define"
	R "TCP/resources"
)

//GetDoorsHandler 获取门信息
func GetDoorsHandler(c *gin.Context) {
	errCode, err, r := R.GetDoors()
	if err != nil {
		log.Errorf("GetDoors Error. ERR: %s", err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, errCode, err.Error())
		return
	}

	D.SuccessWithData(c, http.StatusOK, r)
}

//GetDoorStateHandler 获取门状态
func GetDoorStateHandler(c *gin.Context) {
	/*
		errCode, err, r := R.GetDoorState()
		if err != nil {
			log.Errorf("GetDoorState Error. ERR:%s", err.Error())
			D.ErrorCodeWithMsg(c, http.StatusOK, errCode, err.Error())
			return
		}
	*/
	fmt.Println("test\n")
	D.SuccessWithData(c, http.StatusOK, []map[string]int{
		{
			"door":   1,
			"state":  0,
			"status": 2,
		},
		{
			"door":   2,
			"state":  0,
			"status": 2,
		},
	})
}

//SetDoorStateHandler 远程控制
func SetDoorStateHandler(c *gin.Context) {
	param := make(map[string]int, 0)
	err := D.ParseParam(c, _data, &param)
	if err != nil {
		log.Error(err)
		return
	}

	errCode, err := R.SetDoorState(param, c.ClientIP())
	if err != nil {
		log.Errorf("SetDoorState Error. ERR: %s", err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, errCode, err.Error())
		return
	}

	D.SuccessWithData(c, http.StatusOK, nil)
}

//GetTimeGroupHandler 获取时段信息
func GetTimeGroupHandler(c *gin.Context) {
	var (
		groupNo int
		err     error
	)

	if groupNo, err = D.QueryInt(c, _groupNo); err != nil {
		log.Error(err)
		return
	}

	errCode, err, r := R.GetTimeGroup(groupNo)
	if err != nil {
		log.Errorf("GetTimeGroup Error. ERR: %s", err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, errCode, err.Error())
		return
	}

	D.SuccessWithData(c, http.StatusOK, r)
}

//SetTimeGroupHandler 设置时段信息
func SetTimeGroupHandler(c *gin.Context) {
	param := D.TimeInfo{}
	// 单独写一个参数解析代码
	switch c.ContentType() {
	case D.URLEncoded:
		var p string

		if p = c.PostForm(_data); p == "" {
			D.ErrorCodeWithExtraInfo(c, http.StatusOK, D.EcParamMissing, D.EmParamMissing, _data)
			return
		}

		if !strings.Contains(p, "group_no") {
			D.ErrorCodeWithExtraInfo(c, http.StatusOK, D.EcParamMissing, D.EmParamMissing, _data)
			return
		}

		if err := json.Unmarshal([]byte(p), &param); err != nil {
			D.ErrorCodeWithExtraInfo(c, http.StatusOK, D.EcParamFormat, D.EmParamFormat, err.Error())
			return
		}
	case D.Json:
		b, err := ioutil.ReadAll(c.Request.Body)
		if err != nil {
			D.ErrorCodeWithExtraInfo(c, http.StatusOK, D.EcParamFormat, D.EmParamFormat, err.Error())
			return
		}

		if !strings.Contains(string(b), "group_no") {
			D.ErrorCodeWithExtraInfo(c, http.StatusOK, D.EcParamMissing, D.EmParamMissing, _data)
			return
		}

		if err := json.Unmarshal(b, &param); err != nil {
			D.ErrorCodeWithExtraInfo(c, http.StatusOK, D.EcParamFormat, D.EmParamFormat, err.Error())
			return
		}
	}
	//err := D.ParseParam(c, _data, &param)
	// if err != nill {
	//    log.Error(err)
	//    return
	//}
	log.Debug("param:", param)

	if !ValidateWeek(c, param.Week) {
		log.Errorf("Week Error. ERR: %v", param.Week)
		return
	}

	log.Debugf("validate tz:")

	if !ValidateTimezone(c, param.Timezone) {
		log.Errorf("Timezone Error. ERR: %v", param.Timezone)
		return
	}

	errCode, err := R.SetTimeGroup(param)
	if err != nil {
		log.Errorf("SetTimeGroup Error. ERR: %s", err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, errCode, err.Error())
		return
	}

	D.SuccessWithData(c, http.StatusOK, nil)
}

//ClearTimeGroupHandler 清空时段信息
func ClearTimeGroupHandler(c *gin.Context) {
	param := make(map[string]int, 0)
	err := D.ParseParam(c, _data, &param)
	if err != nil {
		log.Error(err)
		return
	}

	groupNo, ok := param[_groupNo]
	if !ok {
		log.Errorf("%s: %s", D.EmParamMissing, _groupNo)
		D.ErrorCodeWithExtraInfo(c, http.StatusOK, D.EcParamMissing, D.EmParamMissing, _groupNo)
		return
	}

	errCode, err := R.ClearTimeGroup(groupNo)
	if err != nil {
		log.Errorf("ClearTimeGroup Error. ERR: %s", err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, errCode, err.Error())
		return
	}

	D.SuccessWithData(c, http.StatusOK, nil)
}

//GetCardsHandler 获取所有卡信息
func GetCardsHandler(c *gin.Context) {
	errCode, err, r := R.GetCards()
	if err != nil {
		log.Errorf("GetCards Error. ERR: %s", err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, errCode, err.Error())
		return
	}

	D.SuccessWithData(c, http.StatusOK, r)
}

//GetCardHandler 获取卡信息
func GetCardHandler(c *gin.Context) {
	var (
		cardNo string
		err    error
	)

	if cardNo, err = D.QueryString(c, _cardNo); err != nil {
		log.Error(err)
		return
	}

	errCode, err, r := R.GetCard(cardNo)
	if err != nil {
		log.Errorf("GetCard Error. ERR: %s", err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, errCode, err.Error())
		return
	}

	D.SuccessWithData(c, http.StatusOK, r)
}

//AddCardHandler 新增卡信息
func AddCardHandler(c *gin.Context) {
	param := D.CardInfo{}
	err := D.ParseParam(c, _data, &param)
	if err != nil {
		log.Error(err)
		return
	}

	if !ValidateCardNo(c, param.CardNo) {
		log.Errorf("Card No Error. ERR: %s", param.CardNo)
		return
	}

	if !ValidateUserName(c, param.UserName) {
		log.Errorf("UserName Error. ERR: %s", param.UserName)
		return
	}

	if !ValidateCardPassword(c, param.Password) {
		log.Errorf("CardPassword Error. Err: %", param.Password)
		return
	}

	if !ValidateCardFlag(c, param.CardFlag) {
		log.Errorf("CardFlag Error. ERR: %d", param.CardFlag)
		return
	}

	if !ValidateGroupNo(c, param.GroupNo) {
		log.Errorf("GroupNo Error. Err: %d", param.GroupNo)
		return
	}

	errCode, err := R.AddCard(param)

	if err != nil {
		log.Errorf("AddCard Error. ERR: %s", err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, errCode, err.Error())
		return
	}

	D.SuccessWithData(c, http.StatusOK, nil)
}

//SetCardHandler 设置卡信息
func SetCardHandler(c *gin.Context) {
	param := D.CardInfo{}
	err := D.ParseParam(c, _data, &param)
	if err != nil {
		log.Error(err)
		return
	}

	if !ValidateCardNo(c, param.CardNo) {
		log.Errorf("Card No Error. ERR: %s", param.CardNo)
		return
	}

	if !ValidateUserName(c, param.UserName) {
		log.Errorf("UserName Error. ERR: %s", param.UserName)
		return
	}

	if !ValidateCardPassword(c, param.Password) {
		log.Errorf("CardPassword Error. Err: %", param.Password)
		return
	}

	if !ValidateCardFlag(c, param.CardFlag) {
		log.Errorf("CardFlag Error. ERR: %d", param.CardFlag)
		return
	}

	if !ValidateGroupNo(c, param.GroupNo) {
		log.Errorf("GroupNo Error. Err: %d", param.GroupNo)
		return
	}

	errCode, err := R.SetCard(param)
	if err != nil {
		log.Errorf("ModifyCard Error. ERR: %s", err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, errCode, err.Error())
		return
	}

	D.SuccessWithData(c, http.StatusOK, nil)
}

//DeleteCardHandler 删除卡信息
func DeleteCardHandler(c *gin.Context) {
	param := make(map[string]string, 0)
	err := D.ParseParam(c, _data, &param)
	if err != nil {
		log.Error(err)
		return
	}

	cardNo, ok := param[_cardNo]
	if !ok {
		log.Errorf("%s: %s", D.EmParamMissing, _cardNo)
		D.ErrorCodeWithExtraInfo(c, http.StatusOK, D.EcParamMissing, D.EmParamMissing, _cardNo)
		return
	}

	errCode, err := R.DeleteCard(cardNo)
	if err != nil {
		log.Errorf("ClearTimeGroup Error. ERR: %s", err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, errCode, err.Error())
		return
	}

	D.SuccessWithData(c, http.StatusOK, nil)
}

//GetEventHandler 获取记录 获取刷卡记录&门禁告警
func GetEventHandler(c *gin.Context) {
	var (
		recordIndex, alarmIndex int
		err                     error
	)

	if recordIndex, err = D.QueryInt(c, _recordIndex); err != nil {
		log.Error(err)
		return
	}
	if alarmIndex, err = D.QueryInt(c, _alarmIndex); err != nil {
		log.Error(err)
		return
	}

	if recordIndex < 0 {
		D.ErrorCodeWithMsg(c, http.StatusOK, D.EcRecordIndexNotExist, D.EmRecordIndexNotExist)
		return
	}

	if alarmIndex < 0 {
		D.ErrorCodeWithMsg(c, http.StatusOK, D.EcAlarmIndexNotExist, D.EmAlarmIndexNotExist)
		return
	}

	errCode, err, r := R.GetEvent(recordIndex, alarmIndex)
	if err != nil {
		log.Errorf("GetAccessEvent Error. ERR: %s", err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, errCode, err.Error())
		return
	}

	D.SuccessWithData(c, http.StatusOK, r)
}

//GetHistoryEventHandler 获取指定时间段的历史刷卡记录&门
func GetHistoryEventHandler(c *gin.Context) {
	var (
		timeBegin, timeEnd, d string
		door                  []int
		err                   error
	)

	if timeBegin, err = D.QueryString(c, _timeBegin); err != nil {
		log.Error(err)
		return
	}
	if timeEnd, err = D.QueryString(c, _timeEnd); err != nil {
		log.Error(err)
		return
	}

	if d = c.Query(_door); d != "" {
		ds := strings.Split(d, ",")
		door = make([]int, 0, len(ds))
		for _, _ds := range ds {
			_dd, err := strconv.Atoi(_ds)
			if err != nil {
				log.Errorf("Parameter Parsing Error, %s: %s. ERR: %s", _door, c.Query(_door), err.Error())
				D.ErrorCodeWithExtraInfo(c, http.StatusOK, D.EcParamFormat, D.EmParamFormat, err.Error())
				return
			}
			if _dd < 0 {
				D.ErrorCodeWithMsg(c, http.StatusOK, D.EcDoorIDNotExist, D.EmDoorIDNotExist)
				return
			}
			door = append(door, _dd)
		}
	}

	errCode, err, r := R.GetHistoryEvent(timeBegin, timeEnd, door)
	if err != nil {
		log.Errorf("GetHistoryEvent Error. ERR: %s", err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, errCode, err.Error())
		return
	}

	D.SuccessWithData(c, http.StatusOK, r)
}

func CleanDeviceHandler(c *gin.Context) {
	err := R.Reset()
	if err != nil {
		log.Error("clean device error:", err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, D.EcUnknown, err.Error())
		return
	}
	D.SuccessWithData(c, http.StatusOK, nil)
}

func GetCurrentTimeHandler(c *gin.Context) {
	fmt.Printf("GetCurrentTimeHandler = %s", time.Now().Local().Format(D.TimestampFormat)+"+8")
	D.SuccessWithData(c, http.StatusOK, D.TimeManageInfo{
		CurrentTime: time.Now().Local().Format(D.TimestampFormat) + "+8",
	})
}

func SetCurrentTimeHandler(c *gin.Context) {
	var param D.TimeManageInfo
	err := D.ParseParam(c, _data, &param)
	if err != nil {
		log.Error(err)
		return
	}
	log.Infof("set current time %#v", param)
	if len(param.CurrentTime) <= 2 {
		log.Error("current time error:", param.CurrentTime)
		D.ErrorCodeWithMsg(c, http.StatusOK, D.EcParamFormat, D.EmParamFormat)
		return
	}

	t, err := time.Parse(D.TimestampFormat, param.CurrentTime[:len(param.CurrentTime)-2])
	if err != nil {
		log.Error(err)
		D.ErrorCodeWithMsg(c, http.StatusOK, D.EcParamFormat, D.EmParamFormat)
		return
	}

	r, err := D.CmdCommand(fmt.Sprintf("date -s '%s'", t.Format("2006-01-02 15:04:05")))
	if err != nil {
		log.Errorf("sync time result:%s, err:%s", r, err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, D.EcUnknown, err.Error())
		return
	}
	go func() {
		_, err := D.CmdCommand("hwclock -w -u")
		if err != nil {
			log.Error("write time into hw failed: ", err.Error())
		}
	}()
	// 下发指令
	err = R.SetCurrentTime()
	if err != nil {
		log.Error("execute sync time command error:", err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, D.EcUnknown, err.Error())
		return
	}

	D.SuccessWithData(c, http.StatusOK, nil)
}

func GetLogHandler(c *gin.Context) {
	fileName := c.Query(_sn) + ".log"
	if _, err := os.Stat(fileName); err != nil {
		log.Infof("%s not Exist!", fileName)
		D.ErrorCodeWithMsg(c, http.StatusOK, D.EcUnknown, fileName+" not Exist!")
		return
	}
	c.Header("Content-Type", "application/octet-stream")
	c.Header("Content-Disposition", "attachment; filename="+fileName)
	c.Header("Content-Transfer-Encoding", "binary")
	c.File(fileName)
	return
}
func DelLogHandler(c *gin.Context) {
	fileName := c.Query(_sn) + ".log"
	if _, err := os.Stat(fileName); err != nil {
		log.Infof("%s not Exist!", fileName)
		D.ErrorCodeWithMsg(c, http.StatusOK, D.EcUnknown, fileName+" not Exist!")
		return
	}
	if err := os.Remove(fileName); err != nil {
		log.Errorf("remove %s.log file failed,err:%s", fileName, err.Error())
		D.ErrorCodeWithMsg(c, http.StatusOK, D.EcUnknown, fileName+" not Exist!")
		return
	} else {
		log.Debugf("remove %s file success", fileName)
		D.SuccessWithData(c, http.StatusOK, "remove "+fileName+" file success")
		return
	}
	return
}

func GetDrvInfoHandler(c *gin.Context) {
	SN := c.Query(_sn)
	_, err, drvInfo := R.GetDrvInfo(SN)
	if err != nil {

	}
	_, err, CSQ := R.GetCSQRecord(SN)
	if err != nil {

	}
	drvInfoData := &D.DrvInfoData{
		DrvInfo: drvInfo,
		CSQData: CSQ,
	}
	D.SuccessWithData(c, http.StatusOK, drvInfoData)
	return
}
func GetLogInfoHandler(c *gin.Context) {
	pwd, _ := os.Getwd()
	FileInfo := make([]D.FileInfo, 0)
	fileInfo := D.FileInfo{}
	//获取文件或目录相关信息
	fileInfoList, err := ioutil.ReadDir(pwd)
	if err != nil {
		log.Fatal(err)
	}
	for i := range fileInfoList {
		//判断是否为文件
		if !fileInfoList[i].IsDir() {
			//判断后缀是否为log
			fileType := path.Ext(fileInfoList[i].Name())
			if fileType == ".log" {
				fileInfo = D.FileInfo{
					Name:    fileInfoList[i].Name(),
					Size:    D.FormatFileSize(fileInfoList[i].Size()),
					ModTime: fileInfoList[i].ModTime().Format("2006/01/02 15:04:05"),
					Type:    fileType[1:],
					Id:      strings.TrimSuffix(fileInfoList[i].Name(), fileType),
					Path:    pwd,
				}
				FileInfo = append(FileInfo, fileInfo)
			}
		}
	}
	D.SuccessWithData(c, http.StatusOK, FileInfo)
	return
}

//获取指定apn
func GetAPNByPara(c *gin.Context) {
	//http://127.0.0.1:7778/xgd?action=get_apn_by_para&mcc=460&mnc=00
	APNPath := D.APNPath
	fileInfo, err := os.Stat(APNPath)
	if err != nil {
		log.Errorf("get fileInfo [%s] error: %v", APNPath, err)
		D.ErrorCodeWithMsg(c, http.StatusOK, D.EcUnknown, "get fileInfo ["+APNPath+"] error!")
		return
	}
	file, err := os.Open(APNPath)
	if err != nil {
		log.Errorf("Open file [%s] error: %v", APNPath, err)
		return
	}
	defer file.Close()
	data, err := ioutil.ReadAll(file)
	if err != nil {
		log.Errorf("error: %v", err)
		return
	}
	v := D.APNList{}
	v.UpTime = fileInfo.ModTime().Format("2006/01/02 15:04:05")
	err = xml.Unmarshal(data, &v)
	if err != nil {
		log.Errorf("error: %v", err)
		return
	}
	v.ApnNum = len(v.Apn)
	//fmt.Printf("Version = %#v\n", v.Version)
	//fmt.Printf("XMLName = %#v\n", v.XMLName)
	//fmt.Printf("UpTime = %#v\n", v.UpTime)
	//fmt.Printf("len:%d, %+v\n", len(v.Apn), v.Apn[0])
	mcc := c.Query(_mcc)
	mnc := c.Query(_mnc)
	if mcc == "" && mnc == "" {
		D.SuccessWithData(c, http.StatusOK, v)
		return
	}
	//不筛选
	res := D.APNList{
		XMLName: v.XMLName,
		Version: v.Version,
		UpTime:  v.UpTime,
		ApnNum:  0,
	}
	res.Apn = make([]D.APN, 0)
	for _, data := range v.Apn {
		if len(mcc) > 0 {
			if mcc != data.Mcc {
				continue
			}
		}
		if len(mnc) > 0 {
			if mnc != data.Mnc {
				continue
			}
		}
		res.Apn = append(res.Apn, data)
		res.ApnNum++
	}
	D.SuccessWithData(c, http.StatusOK, res)
	return
}
